Cartesian product algorithm